/**
 * @file libetrace/include/libetrace-intvars.h
 * @ingroup libetrace
 */
#ifndef __LIBETRACE_VARS_H_
#define __LIBETRACE_VARS_H_

int trace_enabled_count = 0;

trace_used trace_functions[] = 
  { 
    TRACE_FUNCTIONS_ADD(longjmp),
    TRACE_FUNCTIONS_ADD(_setjmp),
    TRACE_FUNCTIONS_ADD(sigaction),
    TRACE_FUNCTIONS_ADD(snprintf),
    TRACE_FUNCTIONS_ADD(memset),
    TRACE_FUNCTIONS_ADD(gettimeofday),
    TRACE_FUNCTIONS_ADD(write),
    TRACE_FUNCTIONS_ADD(exit),
    { "", 0 }
  };

/**
 * Static part of the file
 */
char trace_file_base[] = "#include <stdio.h>\n"
"#include <setjmp.h>\n"
"#include <signal.h>\n"
"#include <string.h>\n"
"#include <stdlib.h>\n"
"#include <unistd.h>\n"
"#include <sys/time.h>\n"
"#include <sys/resource.h>\n"
"\n"
"#define T_longjmp %slongjmp\n"
"#define T_setjmp %s_setjmp\n"
"\n"
"#define T_sigaction %ssigaction\n"
"#define T_snprintf %ssnprintf\n"
"#define T_memset %smemset\n"
"#define T_gettimeofday %sgettimeofday\n"
"#define T_write %swrite\n"
"#define T_exit %sexit\n"
"\n"
"#define MAX_CHECK_CHAR 3\n"
"#define PRINTABLE(c) (c >= 32 && c <= 126)\n"
"#define STDERR 2\n"
"#define ARG(_size) trace_arg_##_size\n"
"#define WRITENOW() do { T_write(STDERR, logbuf, strlen(logbuf)+1); } while(0)\n"
"#define MAX_CHAR_STR_PRINT 40\n"
"#define STR_REPEAT_CHAR 4\n"
"jmp_buf jBuf;\n"
"#define LOGBUFSIZ 256\n"
"char logbuf[LOGBUFSIZ];\n"
"suseconds_t msec;\n"
"time_t sec;\n"
"u_char siginit = %d;\n"
"u_char no_trace = 0;\n"
"\n"
"#define INITSIGNAL() \\\ndo { if (siginit == 0) { initsignal(); siginit = 1; } } while(0)\n"
"\n"
"static void sigcrash(int signal, siginfo_t *si, void *context)\n"
"{\n"
"  snprintf(logbuf, LOGBUFSIZ - 1, \" [!] The tracer received a signal %%s. \"\n"
"	   \"Currently, the tracer is unable to follow context dependent functions.\\n\"\n"
"	   \"\\t~> Please check previous functions.\\n\", \n"
"	   (signal == SIGILL ? \"SIGILL\" : (signal == SIGFPE ? \"SIGFPE\" : \n"
"					     (signal == SIGBUS ? \"SIGBUS\" : \"SIGSEGV\"))));\n"
"  WRITENOW();\n"
"  T_exit(-1);\n"
"}\n"
"\n"
"static void initsignal()\n"
"{\n"
"  struct sigaction sa;\n"
"	\n"
"  sa.sa_sigaction = (void *) sigcrash;\n"
"  sa.sa_flags = SA_ONSTACK | SA_SIGINFO | SA_NODEFER;\n"
"  \n"
"  sigemptyset(&sa.sa_mask);\n"
"  \n"
"  T_sigaction(SIGSEGV, &sa, NULL);\n"
"  T_sigaction(SIGFPE, &sa, NULL);\n"
"  T_sigaction(SIGILL, &sa, NULL);\n"
"  T_sigaction(SIGBUS, &sa, NULL);\n"
"}\n"
"\n"
"static unsigned char is_string(const void *ptr)\n"
"{\n"
"  int count;\n"
"  char *cptr = (char*) ptr;\n"
"  \n"
"  for (count = 0; PRINTABLE(cptr[count]) && cptr[count] != 0x00; count++)\n"
"    {\n"
"      if (count >= MAX_CHECK_CHAR)\n"
"	return 1;\n"
"    }\n"
"\n"
"  return 0;\n"
"}\n"
"\n"
"static void check_ptr_failed(int nSig)\n"
"{\n"
"  longjmp(jBuf, 1);\n"
"}\n"
"\n"
"static unsigned char check_read_ptr(const void *ptr, unsigned long size)\n"
"{\n"
"  int index;\n"
"  char elem;\n"
"  struct sigaction sa, segvoldsa, busoldsa;\n"
"\n"
"  if (!ptr || size <= 0 || ptr < (void*)0x5000 || ptr == (void *)-1)\n"
"    return 0;\n"
"\n"
"  if(T_setjmp(jBuf))\n"
"    return 0;\n"
"\n"
"  sa.sa_handler = (void *) check_ptr_failed;\n"
"  sa.sa_flags = SA_ONSTACK | SA_RESETHAND | SA_NODEFER;\n"
"  sigemptyset(&sa.sa_mask);\n"
"\n"
"  if (T_sigaction(SIGSEGV, &sa, &segvoldsa) < 0)\n"
"    return 0;\n"
"\n"
"  if (T_sigaction(SIGBUS, &sa, &busoldsa) < 0)\n"
"    return 0;\n"
"\n"
"  for (index = 0; index < size; index++)\n"
"    elem = ((char *)ptr)[index];\n"
"\n"
"  T_sigaction(SIGSEGV, &segvoldsa, NULL);\n"
"  T_sigaction(SIGBUS, &busoldsa, NULL);\n"
"\n"
"  return 1;\n"
"}\n"
"\n"
"static void hex_to_str(const void *ptr)\n"
"{\n"
"  int count;\n"
"  char *cptr = (char*) ptr;\n"
"  unsigned int i;\n"
"\n"
"  T_snprintf(logbuf, LOGBUFSIZ - 1, \" = \");\n"
"  WRITENOW();\n"
"\n"
"  for (i = 0; i < 4; i++)\n"
"  {\n"
"    T_snprintf(logbuf, LOGBUFSIZ - 1, \"0x%%02x\", cptr[i] & 0xFF);\n"
"    WRITENOW();\n"
"\n"
"    if (cptr[i] == '\\n')\n"
"    {\n"
"      \n"
"      T_snprintf(logbuf, LOGBUFSIZ - 1, \" '\\\\n'\"); \n"
"      WRITENOW();\n"
"    }\n"
"    else if (cptr[i] == '\\r')\n"
"    {\n"
"      \n"
"      T_snprintf(logbuf, LOGBUFSIZ - 1, \" '\\\\r'\"); \n"
"      WRITENOW();\n"
"    }\n"
"    else if (cptr[i] == '\\t')\n"
"    {\n"
"      \n"
"      T_snprintf(logbuf, LOGBUFSIZ - 1, \" '\\\\t'\"); \n"
"      WRITENOW();\n"
"    }\n"
"    else if (PRINTABLE(cptr[i]))\n"
"    {\n"
"      T_snprintf(logbuf, BUFSIZ - 1, \" '%%c'\", cptr[i]);\n"
"      WRITENOW();\n"
"    }\n"
"\n"
"    if (i != 3)\n"
"    {\n"
"      T_snprintf(logbuf, BUFSIZ - 1, \" \");\n"
"      WRITENOW();\n"
"    }\n"
"  }\n"
"}\n"
"\n"
"char pad_str[64];\n"
"int pad_count = 0;\n"
"static char *pad_print(int inc)\n"
"{\n"
"  int i;\n"
"\n"
"  if (inc == 0 && pad_count >= 2)\n"
"    pad_count -= 2;\n"
"\n"
"  T_memset(pad_str, ' ', pad_count);\n"
"  pad_str[pad_count] = 0;\n"
"\n"
"  if (inc == 1 && pad_count <= (0xFFFF - 2))\n"
"    pad_count += 2;\n"
"\n"
"  return pad_str;\n"
"}\n"
"\n"
"int setup = 0;\n"
"static void gettrace_time()\n"
"{\n"
"  double difftime = 0;\n"
"  struct timeval now;\n"
"\n"
"  T_gettimeofday(&now, NULL);\n"
"\n"
"  if (setup == 0)\n"
"    {\n"
"      msec = now.tv_usec;\n"
"      sec = now.tv_sec;\n"
"    }\n"
"\n"
"  T_snprintf(logbuf, LOGBUFSIZ - 1, \"%%4d.%%06d \", now.tv_sec - sec, now.tv_usec - msec);\n"
"  WRITENOW();\n"
"\n"
"  if (setup)\n"
"    {\n"
"      msec = now.tv_usec;\n"
"      sec = now.tv_sec;\n"
"    }\n"
"\n"
"  setup = 1;\n"
"}\n"
"static void func_prstr(char *str)\n"
"{\n"
"  unsigned int i, z, count;\n"
"\n"
"  for (i = 0; i < MAX_CHAR_STR_PRINT && str[i] != 0x00; i++, count = 0)\n"
"    {\n"
"      if (str[i+1] == str[i])\n"
"	{\n"
"	  for (count = 0, z = i; z < MAX_CHAR_STR_PRINT && str[z] == str[i]; count++, z++);\n"
"\n"
"	  if (count >= STR_REPEAT_CHAR)\n"
"	    i = z - 1;\n"
"	}\n"
"\n"
"      if (str[i] == '\\n')\n"
"	{\n"
"	  T_snprintf(logbuf, LOGBUFSIZ - 1, \"\\\\n\");\n"
"	  WRITENOW();\n"
"	}\n"
"      else if (str[i] == '\\r')\n"
"	{\n"
"	  T_snprintf(logbuf, LOGBUFSIZ - 1, \"\\\\r\");\n"
"	  WRITENOW();\n"
"	}\n"
"      else if (str[i] == '\\t')\n"
"	{\n"
"	  T_snprintf(logbuf, LOGBUFSIZ - 1, \"\\\\t\");\n"
"	  WRITENOW();\n"
"	}\n"
"      else if (!PRINTABLE(str[i]))\n"
"	{\n"
"	  T_snprintf(logbuf, LOGBUFSIZ - 1, \"\\\\%%d\", (int) (str[i] & 0xFF));\n"
"	  WRITENOW();\n"
"	}\n"
"	else\n"
"	{\n"
"	  T_snprintf(logbuf, LOGBUFSIZ - 1, \"%%c\", str[i]);\n"
"	  WRITENOW();\n"
"	}\n"
"\n"
"      if (count >= STR_REPEAT_CHAR)\n"
"	{\n"
"	  T_snprintf(logbuf, LOGBUFSIZ - 1, \"{%%d times}\", count);\n"
"	  WRITENOW();\n"
"	}\n"
"    }\n"
"\n"
"  if (i >= MAX_CHAR_STR_PRINT)\n"
"    {\n"
"      T_snprintf(logbuf, LOGBUFSIZ - 1, \"...\");	  \n"
"      WRITENOW();\n"
"    }\n"
"}\n"
"\n"
"static void func_intro(const char *fname)\n"
"{\n"
"  INITSIGNAL();\n"
"  gettrace_time();\n"
"  T_snprintf(logbuf, LOGBUFSIZ - 1, \"%%s + %%s(\", pad_print(1), fname);\n"
"  WRITENOW();\n"
"}\n"
"\n"
"static void func_fmtptr(void *ptr, unsigned char readable, unsigned char isstring)\n"
"{\n"
"  T_snprintf(logbuf, LOGBUFSIZ - 1, \"%%s0x%%x\", \n"
"	     readable ? \"*\" : \"\", ptr);\n"
"  WRITENOW();\n"
"\n"
"  if (isstring)\n"
"    {\n"
"      T_snprintf(logbuf, LOGBUFSIZ - 1, \" \\\"\");\n"
"      WRITENOW();	   \n"
"\n"
"      func_prstr((char *)ptr);\n"
"\n"
"      T_snprintf(logbuf, LOGBUFSIZ - 1, \"\\\"\");\n"
"      WRITENOW();	   \n"
"    }\n"
"  else if (readable)\n"
"    {\n"
"      hex_to_str(ptr);\n"
"    }\n"
"}\n"
"  \n"
"static void func_argu(void *ptr, unsigned char first, char *tname, char *aname)\n"
"{\n"
"  unsigned char readable, isstring = 0;\n"
"  readable = check_read_ptr(ptr, MAX_CHECK_CHAR+1);\n"
"\n"
"  if (readable)\n"
"    isstring = is_string(ptr);\n"
"\n"
"  if (!first)\n"
"    {\n"
"      T_snprintf(logbuf, LOGBUFSIZ - 1, \", \");\n"
"      WRITENOW();\n"
"    }\n"
"  \n"
"  if (tname != NULL || aname != NULL)\n"
"    {\n"
"      T_snprintf(logbuf, LOGBUFSIZ - 1, \"%%s %%s: \", tname, aname);\n"
"      WRITENOW();\n"
"    }\n"
"\n"
"  func_fmtptr(ptr, readable, isstring);\n"
"}\n"
"\n"
"static void func_conclu()\n"
"{\n"
"  T_snprintf(logbuf, LOGBUFSIZ - 1, \")\\n%%s\", \"\");\n"
"  WRITENOW(); \n"
"}\n"
"\n"
"static void func_retu(const char *fname, void *ret, int t1, int t2)\n"
"{\n"
"  unsigned char readable, isstring = 0;\n"
"\n"
"  readable = check_read_ptr((void *)ret, MAX_CHECK_CHAR+1);\n"
"\n"
"  if (readable)\n"
"    isstring = is_string(ret);\n"
"\n"
"  gettrace_time();\n"
"\n"
"  T_snprintf(logbuf, LOGBUFSIZ -1, \"%%s - %%s = \", pad_print(0), fname);\n"
"  WRITENOW();\n"
"  func_fmtptr(ret, readable, isstring);\n"
"  T_snprintf(logbuf, LOGBUFSIZ -1, \" [time spent=%%d.%%06d]\\n\", t1, t2);\n"
"  WRITENOW();\n"
"}\n";

char *last_parsed_function = NULL;

#endif
